package wwl.lsf.hellospringboot.test.多线程题;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

class FooBar {

  private int n;


  private ReentrantLock lock = new ReentrantLock();

  private Condition fooTurn = lock.newCondition();
  private Condition barTurn = lock.newCondition();

  CountDownLatch countDownLatch = new CountDownLatch(1);


  public FooBar(int n) {
    this.n = n;
  }

  public void foo(Runnable printFoo) throws InterruptedException {

    try {
      lock.lock();
      for (int i = 0; i < n; i++) {

        printFoo.run();
        countDownLatch.countDown();

        barTurn.signal();

        fooTurn.await();

      }
      barTurn.signal();
    } catch (InterruptedException e) {
      e.printStackTrace();
    } finally {
      lock.unlock();
    }
  }

  public void bar(Runnable printBar) throws InterruptedException {
    countDownLatch.await();
    try {
      lock.lock();
      for (int i = 0; i < n; i++) {

        printBar.run();

        fooTurn.signal();

        barTurn.await();

      }

      fooTurn.signal();
    } catch (InterruptedException e) {
      e.printStackTrace();
    } finally {
      lock.unlock();
    }
  }

  public static void main(String[] args) {
    FooBar fooBar = new FooBar(3);

    Thread t1 = new Thread(() -> {
      try {
        fooBar.foo(() -> {
          System.out.println("foo");
        });
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }, "糖糖的线程1");

    Thread t2 = new Thread(() -> {
      try {
        fooBar.bar(() -> {
          System.out.println("bar");
        });
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }, "糖糖的线程2");

    t2.start();
    t1.start();


  }
}